package com.kding.deviceunique

import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import android.os.Handler
import android.text.TextUtils
import android.util.Log
import com.bun.miitmdid.core.ErrorCode
import com.bun.miitmdid.core.MdidSdkHelper
import com.bun.miitmdid.interfaces.IIdentifierListener
import com.bun.miitmdid.interfaces.IdSupplier
import com.kding.deviceunique.interfaces.IgetUUIDListener
import com.kding.deviceunique.utils.Encryption
import com.kding.deviceunique.utils.FileUtil

/**
 * 获取用户唯一标识
 *
 *  android23以上的先判断本地是否有记录，如果有记录则直接读取记录，
 *  如果没有记录则直接去获取用户OAID
 *  如果获取不到用户OAID则自己生成一个根据IMEI匹配的key
 *  如果手机权限不给则无法获取准确imei,则会根据用户当前创建一个key
 *  key存储以文件和sp存储，以文件为主
 */
@SuppressLint("StaticFieldLeak")
class OAIDHelper {
    companion object : IIdentifierListener {
        var instance: OAIDHelper? = null
            get() {
                if (field == null) {
                    field = OAIDHelper()
                }
                return field
            }

        @Synchronized
        fun get(): OAIDHelper {
            return instance!!
        }

        //不安全
        var oaid: String = ""
            get

        //安全获取
        @JvmStatic
        fun getUUID(cxt: Context): String {
            //首次获取设备好一定会是空字符串
            if (TextUtils.isEmpty(oaid)) {
                val uuid = FileUtil.getUUID(cxt.applicationContext)
                if (!TextUtils.isEmpty(uuid)) {
                    return uuid
                } else {
                    return UUIDUtils.getUniqueID(cxt.applicationContext)
                }
            } else {
                return oaid
            }
        }

        private var context: Context? = null
        private var callback: IgetUUIDListener? = null

        @JvmStatic
        fun init(context: Context, callback: IgetUUIDListener) {
            this.context = context.applicationContext
            this.callback = callback
            //首次安装获取设备号一定会是空字符串
            val uuid = FileUtil.saveUUID(context.applicationContext, oaid)
            if (uuid == "") {
                getDeviceIds(context.applicationContext)
            } else {
                callback?.let {
                    oaid = uuid
                    it.returnUUID(uuid)
                    onFree()
                }
            }
        }

        @JvmStatic
        private val handler = Handler {
            if (it.what == Constants.mHandlerKey) {
                setUUIDCallBack(context)
            }
            false
        }

        /**
         * 获取设备信息
         */
        @JvmStatic
        private fun getDeviceIds(cxt: Context?): Int {
            if (Build.VERSION.SDK_INT >= 29) {
                //调用初始化方法
                val nres = MdidSdkHelper.InitSdk(cxt, true, this)
                var tips = ""
                when (nres) {
                    ErrorCode.INIT_ERROR_DEVICE_NOSUPPORT -> { //不支持的设备
                        tips = "不支持的设备"
                    }
                    ErrorCode.INIT_ERROR_LOAD_CONFIGFILE -> { //加载配置文件出错
                        tips = "加载配置文件出错"
                    }
                    ErrorCode.INIT_ERROR_MANUFACTURER_NOSUPPORT -> { //不支持的设备厂商
                        tips = "不支持的设备厂商"
                    }
                    ErrorCode.INIT_ERROR_RESULT_DELAY -> { //获取接口是异步的，结果会在回调中返回，回调执行的回调可能在工作线程
                        tips = "获取接口是异步的，结果会在回调中返回，回调执行的回调可能在工作线程"
                        handler.sendEmptyMessageDelayed(Constants.mHandlerKey, 2000)
                    }
                    ErrorCode.INIT_HELPER_CALL_ERROR -> { //反射调用出错
                        tips = "反射调用出错"
                    }
                    else -> {
                        tips = "其他错误请联系管理员！"
                    }
                }
                if (nres != ErrorCode.INIT_ERROR_RESULT_DELAY) {
                    setUUIDCallBack(cxt)
                }
                Log.e("OAIDHelper", "return value:$tips")
                return nres
            } else {
                setUUIDCallBack(cxt)
                return -1
            }
        }

        @JvmStatic
        private fun setUUIDCallBack(cxt: Context?) {
            //如果去OAID如果没有获取到数据则直接走自己设备好生成器并回调
            oaid = UUIDUtils.getUniqueID(cxt)
            callback?.let { xx ->
                xx.returnUUID(oaid)
                onFree()
            }
            handler.removeMessages(Constants.mHandlerKey)
        }

        @JvmStatic
        fun onFree() {
            Log.e("TAG22", "onFree")
            callback = null
            context = null
        }

        /**
         * 这里的回调还是在异步线程里的执行结束之后需要回到主线执行
         */
        override fun OnSupport(boolean: Boolean, idSupplier: IdSupplier?) {
            if (idSupplier == null) {
                return
            }
            val supplierOAID = idSupplier.oaid.toString()
            if (supplierOAID.countStr("0000") > 5 || TextUtils.isEmpty(supplierOAID)) {
                //判别是否开启了广告屏蔽,或者OAID获取为空的情况下 也是默认给生成一个，
                oaid = UUIDUtils.getUniqueID(context)
            } else {
                oaid = Encryption.md5(supplierOAID)
            }
            FileUtil.saveUUID(context, oaid)
            context?.let { it ->
                Handler(it.mainLooper).post {
                    callback?.let { xx ->
                        xx.returnUUID(oaid)
                        handler.removeMessages(Constants.mHandlerKey)
                        onFree()
                    }
                }
            }
        }
    }
}